#include <time.h>
#include <fcntl.h>
#include <errno.h>
#include "epollsvrio.h"
#include "defines.h"

int SetNonBlocking(int sock)
{
	int opts;
	opts=fcntl(sock,F_GETFL);
	if(opts<0)
	{
		perror("fcntl(sock,GETFL)");
		return -1;
	}
	opts = opts|O_NONBLOCK;
	if(fcntl(sock,F_SETFL,opts)<0)
	{
		perror("fcntl(sock,SETFL,opts)");
		return -2;
	}
	return 0;
}

CEpollSvrIO::CEpollSvrIO(char*sIP, const short iPort) :
CSvrIO(sIP, iPort)
{
	m_epfd = epoll_create(10);
	m_AddrLen = sizeof(sockaddr_in);
}

void CEpollSvrIO::PrepareListenfd( )
{
	int reuseaddr = 1;
	setsockopt(m_iListenFd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(int));
	SetNonBlocking(m_iListenFd);
	epoll_event ev;
	ev.data.fd=m_iListenFd;
	ev.events=EPOLLIN|EPOLLET;
	epoll_ctl(m_epfd,EPOLL_CTL_ADD,m_iListenFd,&ev);
}

int CEpollSvrIO::ProcessEvent() {
	//while(true)
	//{
	int nfds = epoll_wait(m_epfd,m_Events,MAX_EVENT,-1);
	if ( nfds == -1)
	{
		if ( errno==EINTR )//被中断
		{
			//continue;
			return -1;
		}
		//break;
	}
	if ( nfds == 0 )
	{
		printf( "epoll_wait is timeout\n" );
		return -2;
		//continue;
	}
	
	for( int i = 0;i<nfds;i++ )
	{
		if(m_Events[i].data.fd==m_iListenFd) 			
		{
			int connfd = 0;
			while( (connfd=accept(m_iListenFd,(sockaddr*)&m_ClientAddr,&m_AddrLen ))>0)
			{
				this->OnConnect(connfd,(sockaddr*)&m_ClientAddr);
			}

		}
		else if( m_Events[i].events&EPOLLIN )
		{
			Connection*pConn = (Connection*)m_Events[i].data.ptr;
			this->OnRead( pConn );
		}

		else if(m_Events[i].events&EPOLLOUT)
		{
			Connection*pConn = (Connection*)m_Events[i].data.ptr;
			this->OnWrite( pConn );
		}
	}

	return 0;
	//}

}

void CEpollSvrIO::AddConn( Connection*pConn,unsigned char flag )
{	

	struct epoll_event ev;
	ev.data.fd = pConn->fd;
	if ( flag&READ_EVENT )ev.events|=EPOLLIN;
	if ( flag&WRITE_EVENT)ev.events|=EPOLLOUT;
	if ( flag&CLEAR_EVENT)ev.events|=EPOLLET;

	ev.data.ptr = pConn;
	epoll_ctl(m_epfd,EPOLL_CTL_ADD,pConn->fd,&ev);
}
